/*
 * Copyright (c) 2008 Sun Microsystems, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
package org.sunspotworld.manager;

import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.peripheral.TimeoutException;
import java.util.Calendar;
import java.util.Date;
import javax.microedition.io.*;
import org.sunspotworld.executor.DataExecutor;

/**
 * This class provides all the WSN relate operation
 * @author lailiaidi
 * Change from DatabaseDemo by
 * @author: Vipul Gupta
 */
public class WSNManager {
    // Broadcast port on which we listen for sensor samples
    private static final int DATA_SINK_PORT = 70;
    // Duration (in milliseconds) for which to collect samples.
    private static final int SAMPLING_DURATION = 60000; //1 minute
    // This is how long we block waiting to read data on the radio connection. Without a timeout, the host application
    // could run well beyond the duration specified above, e.g. if there are no SPOTs transmitting sensor samples.
    private static final int CONNECTION_TIMEOUT = 10000; //10 seconds
    private RadiogramConnection obRadiogramConn = null;
    private DataExecutor obDataExecutor;
    private String obStrGatewayAddr;
    private String obStrGatewayLocation;
    private String obStrGatewayName;

    /**
     * This the constructore of WSNManager class
     * @param obDataExecutor
     * @param obStrGatewayAddr
     * @param obStrGatewayName
     * @param obStrGatewayLocation 
     */
    public WSNManager(DataExecutor obDataExecutor, String obStrGatewayAddr, String obStrGatewayName, String obStrGatewayLocation) {
        this.obDataExecutor = obDataExecutor;
        this.obStrGatewayAddr = obStrGatewayAddr;
        this.obStrGatewayName = obStrGatewayName;
        this.obStrGatewayLocation = obStrGatewayLocation;
    }

    /**
     * This method is used to start WSN daemon
     * @return 
     */
    public boolean startWSN() {
        try {
            //Connect to WSN Mote
            System.out.println("\nStarting WSN Basestation ... ");
            // Let's also open up a server-side broadcast radiogram connection
            // on which to listen for sensor readings being sent by different SPOTs
            obRadiogramConn = (RadiogramConnection) Connector.open("radiogram://:" + DATA_SINK_PORT);
            // wait a finite time for data to arrive whenever we call receive()
            obRadiogramConn.setTimeout(CONNECTION_TIMEOUT);
        } catch (Exception e) {
            System.err.println("ERROR: Starting WSN was fail: " + e.getMessage());
            return false;
        }

        try {
            // Open up a server-side broadcast radiogram connection
            // to listen for sensor readings being sent by different SPOTs
            dg = obRadiogramConn.newDatagram(obRadiogramConn.getMaximumLength());
        } catch (Exception e) {
            //System.err.println("ERROR in collectData: " + e.getMessage() + " while reading sensor samples 1.");
            //return false;
        }
        return true;
    }

    /**
     * 
     * This method is used to stop WSN daemon
     */
    public void stopWSN() {
        try {
            if (obRadiogramConn != null) {
                obRadiogramConn.close();
            }
        } catch (Exception e) {
        }
    }
    Datagram dg = null;
    String obStrSpotAddr = null;
    String obTimeStamp = null;
    int obIntLight = 0;
    double obDoubleTemp = 0;
    double obDoubleBatt = 0;
    long start = 0L;

    /**
     * This method is used to handle data collection from WSN mote to the MySQL database
     * Put it into File
     */
    public void collectData() {
        try {
            // Read sensor sample received over the radio
            obRadiogramConn.receive(dg);
            obStrSpotAddr = dg.getAddress();// read sender's Id
            obTimeStamp = dg.readUTF();  // read time stamp for the reading
            obIntLight = dg.readInt(); // read the light value
            obDoubleTemp = dg.readDouble(); //read the temperature value
            obDoubleBatt = dg.readDouble();//read the battery value

            //If the sensor not sending valid timestamp
            if (obTimeStamp == null || obTimeStamp.length() == 0) {
                Calendar obCal = Calendar.getInstance();
                String obStrCalender = null;
                long obLongNow = System.currentTimeMillis();
                obCal.setTime(new Date(obLongNow));
                obStrCalender = obCal.get(Calendar.YEAR) + "-"
                        + (1 + obCal.get(Calendar.MONTH)) + "-"
                        + obCal.get(Calendar.DAY_OF_MONTH) + " "
                        + obCal.get(Calendar.HOUR_OF_DAY) + ":"
                        + obCal.get(Calendar.MINUTE) + ":"
                        + obCal.get(Calendar.SECOND);
                obTimeStamp = obStrCalender;
            }
            //Set Flag as 0 so this engine will send the data  to the DTN network
            int obFlag = 0;
            System.out.println("* spotId:" + obStrSpotAddr + ", timestamp:" + obTimeStamp + ", light:" + obIntLight + ", temperature: " + obDoubleTemp + ", battery: " + obDoubleBatt);

            //Write this data to database
            obDataExecutor.writeSensingTable(obStrGatewayAddr, obStrGatewayName, obStrGatewayLocation, obStrSpotAddr, "unknown location", obTimeStamp, obIntLight, obDoubleTemp, obDoubleBatt, obFlag);

        } catch (TimeoutException e) {
            System.err.println("!");
        } catch (Exception e) {
            //System.err.println("ERROR in collectData: " + e.getMessage() + " while reading sensor samples 2.");
            // return false;
        }
    }
}
